package com.yunxin.admin.system.infra.framework.security.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.yunxin.admin.system.infra.common.constant.SystemConstants;
import com.yunxin.admin.system.infra.framework.security.userdetails.SysUserDetails;
import com.yunxin.admin.system.infra.persistence.mapper.SysMenuMapper;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.common.result.ResultCode;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.PatternMatchUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zero°
 * @since 2023-05-22
 */
public enum SecurityUtils {
    /**
     * 实例
     */
    X;

    private static final String ROLE_CACHE_KEY = "ROLE_";

    /**
     * 获取当前登录人信息
     *
     * @return SysUserDetails
     */
    public SysUserDetails getUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            Object principal = authentication.getPrincipal();
            if (principal instanceof SysUserDetails sysUserDetails) {
                return sysUserDetails;
            }
        }
        throw new BusinessException(ResultCode.USER_NOT_EXIST);
    }

    /**
     * 获取用户ID
     *
     * @return Long
     */
    public Long getUserId() {
        return Convert.toLong(getUser().getUserId());
    }

    /**
     * 获取部门ID
     *
     * @return Long
     */
    public Long getDeptId() {
        return Convert.toLong(getUser().getDeptId());
    }

    /**
     * 获取数据权限范围
     *
     * @return DataScope
     */
    public Integer getDataScope() {
        return Convert.toInt(getUser().getDataScope());
    }


    /**
     * 获取用户角色集合
     *
     * @return Set<String>
     */
    public Set<String> getRoles() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            if (CollUtil.isNotEmpty(authorities)) {
                return authorities.stream().filter(item -> item.getAuthority().startsWith(ROLE_CACHE_KEY))
                        .map(item -> CharSequenceUtil.removePrefix(item.getAuthority(), ROLE_CACHE_KEY))
                        .collect(Collectors.toSet());
            }
        }
        return Collections.emptySet();
    }

    /**
     * 获取用户权限集合
     *
     * @return Set<String>
     */
    public Set<String> getPerms() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            if (CollUtil.isNotEmpty(authorities)) {
                return authorities.stream().map(GrantedAuthority::getAuthority)
                        .filter(authority -> !authority.startsWith(ROLE_CACHE_KEY))
                        .collect(Collectors.toSet());
            }
        }
        return Collections.emptySet();
    }

    /**
     * 是否超级管理员
     * <p>
     * 超级管理员忽视任何权限判断
     *
     * @return boolean
     */
    public boolean isRoot() {
        Set<String> roles = getRoles();
        return roles.contains(SystemConstants.ROOT_ROLE_CODE);
    }

    /**
     * 是否业务员
     * @return boolean
     */
    public boolean isSalesmanUser() {
        Set<String> roles = getRoles();
        return roles.contains(SystemConstants.BOKE_BUSINESS);
    }

    /**
     * 是否话务员
     * @return boolean
     */
    public boolean isTelephonerUser() {
        Set<String> roles = getRoles();
        return roles.contains(SystemConstants.BOKE_TELEPHONE);
    }

    /**
     * 是否为波克团队管理员
     * @return
     */
    public boolean isBokeTeamUser() {
        Set<String> roles = getRoles();
        return roles.contains(SystemConstants.BOKE_TEAM_USER);
    }

    /**
     * 是否为波克商户管理员
     * @return
     */
    public boolean isBokeMerchantUser() {
        Set<String> roles = getRoles();
        return roles.contains(SystemConstants.BOKE_MERCHANT_ADMIN);
    }
    //除开话务员的角色集合
    public List<String> getRoleCodeExcepTelephoneList(){
        List<String> codeList=new ArrayList<>();
        codeList.add(SystemConstants.BOKE_MERCHANT_ADMIN);
        codeList.add(SystemConstants.BOKE_TEAM_USER);
        codeList.add(SystemConstants.BOKE_BUSINESS);
        return codeList;
    }

    public List<String> getRoleCodeList(){
        List<String> codeList=new ArrayList<>();
        codeList.add(SystemConstants.BOKE_MERCHANT_ADMIN);
        codeList.add(SystemConstants.BOKE_TEAM_USER);
        codeList.add(SystemConstants.BOKE_TELEPHONE);
        codeList.add(SystemConstants.BOKE_BUSINESS);
        return codeList;
    }


    /**
     * 是否拥有权限判断
     * <p>
     * 适用业务判断(接口权限判断适用Spring Security 自带注解 PreAuthorize 判断即可 )
     *
     * @return boolean
     */
    public boolean hasPerm(String perm) {
        if (isRoot()) {
            return true;
        }
        Set<String> perms = getPerms();
        return perms.stream().anyMatch(item -> PatternMatchUtils.simpleMatch(perm, item));
    }

    /**
     * 检查是否有对应菜单
     * @param menuId
     */
    public boolean checkMenu(long menuId) {

        SysMenuMapper mapper = SpringUtil.getBean(SysMenuMapper.class);
        Long userId = getUser().getUserId();
        Integer checked = mapper.checkMenuId(menuId, userId);
        if (Objects.isNull(checked) || checked == 0) {
            return false;
        }
        return true;
    }
}
